home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / mtools.lha / mtools-2.0.7 / mread.c < prev    next >
C/C++ Source or Header  |  1992-09-10  |  8KB  |  368 lines

  1. /*
  2.  * Read (copy) an MSDOS file to Unix
  3.  *
  4.  * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  5.  * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  6.  * fthood!egray@uxc.cso.uiuc.edu    Directorate of Engineering & Housing
  7.  *                     Environmental Management Office
  8.  *                     Fort Hood, TX 76544-5057
  9.  */
  10.  
  11. #define LOWERCASE
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #ifdef BSD
  18. #include <sys/time.h>
  19. #else /* BSD */
  20. #include <time.h>
  21. #endif /* BSD */
  22. #include "msdos.h"
  23. #include "patchlevel.h"
  24.  
  25. int fd = -1;                /* the file descriptor for the device */
  26. int dir_start;                /* starting sector for directory */
  27. int dir_len;                /* length of directory (in sectors) */
  28. int dir_entries;            /* number of directory entries */
  29. int clus_size;                /* cluster size (in sectors) */
  30. char *mcwd;                /* the Current Working Directory */
  31. int fat_error;                /* FAT error detected? */
  32.  
  33. static void set_mtime();
  34. static FILE *open_file();
  35. static long conv_stamp();
  36.  
  37. main(argc, argv)
  38. int argc;
  39. char *argv[];
  40. {
  41.     FILE *fp;
  42.     extern int optind;
  43.     extern char *optarg;
  44.     int i, ismatch, entry, single, c, oops, preserve, nowarn, textmode;
  45.     int got_one, missed_one;
  46.     unsigned int fat;
  47.     long size, mtime;
  48.     char *filename, *newfile, *get_name(), *unix_name(), *pathname;
  49.     char *get_path(), *target, tmp[MAX_PATH], *strcat(), *strcpy(), drive;
  50.     char get_drive(), last_drive, *fix_mcwd(), *s;
  51.     void exit();
  52.     struct directory *dir, *dir_read();
  53.     struct stat stbuf;
  54.  
  55.                     /* get command line options */
  56.     oops = 0;
  57.     preserve = 0;
  58.     nowarn = 0;
  59.     textmode = 0;
  60.     got_one = 0;
  61.     missed_one = 0;
  62.     while ((c = getopt(argc, argv, "tnmv")) != EOF) {
  63.         switch (c) {
  64.             case 't':
  65.                 textmode = 1;
  66.                 break;
  67.             case 'n':
  68.                 nowarn = 1;
  69.                 break;
  70.             case 'm':
  71.                 preserve = 1;
  72.                 break;
  73.             case 'v':    /* dummy option for mcopy */
  74.                 break;
  75.             default:
  76.                 oops = 1;
  77.                 break;
  78.         }
  79.     }
  80.  
  81.     if (oops || (argc - optind) < 2) {
  82.         fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE);
  83.         fprintf(stderr, "Usage: %s [-tnm] msdosfile unixfile\n", argv[0]);
  84.         fprintf(stderr, "       %s [-tnm] msdosfile [msdosfiles...] unixdirectory\n", argv[0]);
  85.         exit(1);
  86.     }
  87.     last_drive = 'x';
  88.     mcwd = fix_mcwd();
  89.                     /* only 1 file to copy... */
  90.     single = 1;
  91.     target = argv[argc - 1];
  92.                     /* ...unless last arg is a directory */
  93.     if (!stat(target, &stbuf)) {
  94.         if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
  95.             single = 0;
  96.     }
  97.                     /* too many arguments */
  98.     if (single && (argc - optind) != 2) {
  99.         fprintf(stderr, "%s: Too many arguments or destination directory omitted\n", argv[0]);
  100.         exit(1);
  101.     }
  102.  
  103.     for (i = optind; i < argc - 1; i++) {
  104.         drive = get_drive(argv[i]);
  105.         if (drive != last_drive) {
  106.             if (init(drive, 0)) {
  107.                 fprintf(stderr, "%s: Cannot initialize '%c:'\n", argv[0], drive);
  108.                 missed_one++;
  109.                 continue;
  110.             }
  111.             last_drive = drive;
  112.         }
  113.         filename = get_name(argv[i]);
  114.         pathname = get_path(argv[i]);
  115.         if (subdir(drive, pathname)) {
  116.             missed_one++;
  117.             continue;
  118.         }
  119.  
  120.         ismatch = 0;
  121.         for (entry = 0; entry < dir_entries; entry++) {
  122.             dir = dir_read(entry);
  123.                     /* if empty */
  124.             if (dir->name[0] == 0x0)
  125.                 break;
  126.                     /* if erased */
  127.             if (dir->name[0] == 0xe5)
  128.                 continue;
  129.                     /* if dir or volume label */
  130.             if ((dir->attr & 0x10) || (dir->attr & 0x08))
  131.                 continue;
  132.  
  133.             newfile = unix_name(dir->name, dir->ext);
  134.  
  135.                     /* if single file */
  136.             if (single) {
  137.                 if (!strcmp(newfile, filename)) {
  138.                     fat = dir->start[1] * 0x100 + dir->start[0];
  139.                     size = dir->size[3] * 0x1000000L + dir->size[2] * 0x10000L + dir->size[1] * 0x100 + dir->size[0];
  140.                     if (preserve)
  141.                         mtime = conv_stamp(dir->time, dir->date);
  142.                     else
  143.                         mtime = 0L;
  144.                     if ((fp = open_file(target, nowarn))) {
  145.                         if (file_read(fp, fat, textmode, 0, size)) {
  146.                             fclose(fp);
  147.                             missed_one++;
  148.                             break;
  149.                         }
  150.                         fclose(fp);
  151.                         set_mtime(target, mtime);
  152.                         ismatch = 1;
  153.                         got_one++;
  154.                     }
  155.                     else
  156.                         missed_one++;
  157.                     break;
  158.                 }
  159.             }
  160.                     /* if multiple files */
  161.             else {
  162.                 if (match(newfile, filename)) {
  163.                     fat = dir->start[1] * 0x100 + dir->start[0];
  164.                     size = dir->size[3] * 0x1000000L + dir->size[2] * 0x10000L + dir->size[1] * 0x100 + dir->size[0];
  165.                     if (preserve)
  166.                         mtime = conv_stamp(dir->time, dir->date);
  167.                     else
  168.                         mtime = 0L;
  169.                     printf("Copying %s\n", newfile);
  170. #ifdef LOWERCASE
  171.                     s = newfile;
  172.                     while (*s) {
  173.                         if (isupper(*s))
  174.                             *s = tolower(*s);
  175.                         s++;
  176.                     }
  177. #endif /* LOWERCASE */
  178.                     strcpy(tmp, target);
  179.                     strcat(tmp, "/");
  180.                     strcat(tmp, newfile);
  181.                     if ((fp = open_file(tmp, nowarn))) {
  182.                         if (file_read(fp, fat, textmode, 0, size)) {
  183.                             fclose(fp);
  184.                             missed_one++;
  185.                             break;
  186.                         }
  187.                         fclose(fp);
  188.                         set_mtime(tmp, mtime);
  189.                         ismatch = 1;
  190.                         got_one++;
  191.                     }
  192.                     else
  193.                         missed_one++;
  194.                 }
  195.             }
  196.         }
  197.         if (fat_error) {
  198.             missed_one++;
  199.             break;
  200.         }
  201.  
  202.         if (!ismatch) {
  203.             fprintf(stderr, "%s: File \"%s\" not found\n", argv[0], filename);
  204.             missed_one++;
  205.         }
  206.     }
  207.     close(fd);
  208.     if (got_one && missed_one)
  209.         exit(2);
  210.     if (missed_one)
  211.         exit(1);
  212.     exit(0);
  213. }
  214.  
  215. /*
  216.  * Open the named Unix file for write.
  217.  */
  218.  
  219. static FILE *
  220. open_file(target, nowarn)
  221. char *target;
  222. int nowarn;
  223. {
  224.     static FILE *fp;
  225.     char ans[10];
  226.     struct stat stbuf;
  227.  
  228.     if (!nowarn) {
  229.         if (!access(target, 0)) {
  230.             /* CONSTCOND */
  231.             while (1) {
  232.                 printf("File \"%s\" exists, overwrite (y/n) ? ", target);
  233.                 gets(ans);
  234.                 if (ans[0] == 'n' || ans[0] == 'N')
  235.                     return(NULL);
  236.                 if (ans[0] == 'y' || ans[0] == 'Y')
  237.                     break;
  238.             }
  239.                     /* sanity checking */
  240.             if (!stat(target, &stbuf)) {
  241.                 if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
  242.                     fprintf(stderr, "\"%s\" is not a regular file\n", target);
  243.                     return(NULL);
  244.                 }
  245.             }
  246.         }
  247.     }
  248.  
  249.     if (!(fp = fopen(target, "w"))) {
  250.         fprintf(stderr, "Can't open \"%s\" for write\n", target);
  251.         return(NULL);
  252.     }
  253.     return(fp);
  254. }
  255.  
  256. /*
  257.  * Convert an MSDOS time & date stamp to the Unix time() format
  258.  */
  259.  
  260. static long
  261. conv_stamp(time_field, date_field)
  262. unsigned char *time_field, *date_field;
  263. {
  264. #ifdef BSD
  265.     struct timeval tv;
  266.     struct timezone tz;
  267. #else /* BSD */
  268.     extern long timezone;
  269.     void tzset();
  270. #endif /* BSD */
  271.     struct tm *tmbuf, *localtime();
  272.     int year, mon, mday, hour, min, sec, old_leaps;
  273.     long answer, sec_year, sec_mon, sec_mday, sec_hour, sec_min, sec_leap;
  274.     long tzone, dst;
  275.     static int month[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304,
  276.     334};
  277.                     /* dissect the parts */
  278.     year = (date_field[1] >> 1) + 1980;
  279.     mon = (((date_field[1] & 0x1) << 3) + (date_field[0] >> 5));
  280.     mday = date_field[0] & 0x1f;
  281.     hour = time_field[1] >> 3;
  282.     min = (((time_field[1] & 0x7) << 3) + (time_field[0] >> 5));
  283.     sec = (time_field[0] & 0x1f) * 2;
  284.                     /* how many previous leap years */
  285.     old_leaps = (year - 1972) / 4L;
  286.     sec_leap = old_leaps * 24L * 60L * 60L;
  287.                     /* back off 1 day if before 29 Feb */
  288.     if (!(year % 4) && mon < 3)
  289.         sec_leap -= 24L * 60L * 60L;
  290.     sec_year = (year - 1970) * 365L * 24L * 60L * 60L;
  291.     sec_mon = month[mon - 1] * 24L * 60L * 60L;
  292.     sec_mday = mday * 24L * 60L * 60L;
  293.     sec_hour = hour * 60L * 60L;
  294.     sec_min = min * 60L;
  295.                     /* correct for Time Zone */
  296. #ifdef BSD
  297.     gettimeofday(&tv, &tz);
  298.     tzone = tz.tz_minuteswest * 60L;
  299. #else /* BSD */
  300.     tzset();
  301.     tzone = timezone;
  302. #endif /* BSD */
  303.  
  304.     answer = sec_leap + sec_year + sec_mon + sec_mday + sec_hour + sec_min + sec + tzone;
  305.                     /* correct for Daylight Saving Time */
  306.     tmbuf = localtime(&answer);
  307.     dst = (tmbuf->tm_isdst) ? (-60L * 60L) : 0L;
  308.     answer += dst;
  309.     
  310.     return(answer);
  311. }
  312.  
  313. /*
  314.  * Preserve the file modification times after the fclose()
  315.  */
  316.  
  317. static void
  318. set_mtime(target, mtime)
  319. char *target;
  320. long mtime;
  321. {
  322. #ifdef BSD
  323.     struct timeval tv[2];
  324.  
  325.     if (mtime != 0L) {
  326.         tv[0].tv_sec = mtime;
  327.         tv[0].tv_usec = 0;
  328.         tv[1].tv_sec = mtime;
  329.         tv[1].tv_usec = 0;
  330.         utimes(target, tv);
  331.     }
  332. #else /* BSD */
  333.     struct {
  334.         time_t actime;
  335.         time_t modtime;
  336.     } utbuf;
  337.  
  338.     if (mtime != 0L) {
  339.         utbuf.actime = mtime;
  340.         utbuf.modtime = mtime;
  341.         utime(target, &utbuf);
  342.     }
  343. #endif /* BSD */
  344.     return;
  345. }
  346.  
  347. /*
  348.  * stubs for read-only programs
  349.  */
  350.  
  351. void
  352. disk_flush()
  353. {
  354.     extern int disk_dirty;
  355.  
  356.     disk_dirty = 0;
  357.     return;
  358. }
  359.  
  360. void
  361. dir_flush()
  362. {
  363.     extern int dir_dirty;
  364.  
  365.     dir_dirty = 0;
  366.     return;
  367. }
  368.